
Imports System
Imports System.Data
Imports System.Diagnostics
Imports System.Drawing
Imports System.Data.SqlClient
Imports System.IO
Imports _2bMatesSite.Common

Namespace _2bMatesSite.BO
	''' <summary>
	''' Base class for picture objects.
	''' </summary>
	Public MustInherit Class Picture
		Protected id As Integer

		Protected name As String
		Protected desc As String
		Protected img As Bitmap

		Public Sub New(ByVal img As Bitmap, ByVal name As String, ByVal desc As String)
			id = -1
			Me.name = name
			Me.desc = desc
			Me.img = img
		End Sub

		' Loads an image from a data reader
		Public Sub New(ByVal dr As SqlDataReader)
			id = -1
			LoadFromReader(dr)
		End Sub

		'
		' Public properties
		'

		Public ReadOnly Property ID() As Integer
			Get
				Return id
			End Get
		End Property

		Public Property Name() As String
			Get
				Return name
			End Get

			Set
				name = value
			End Set
		End Property

		Public Property Desc() As String
			Get
				Return desc
			End Get

			Set
				desc = value
			End Set
		End Property

		Public ReadOnly Property Bitmap() As Bitmap
			Get
				Return GetImage()
			End Get
		End Property

		Public Sub Save()
			If id < 0 Then
				DoInsert()
			Else
				DoUpdate()
			End If
		End Sub


		'
		' Private and protected methods
		'

		' Loads the image if not already loaded
		Protected Function GetImage() As Bitmap
			If img = Nothing Then
				img = LoadImage()
			End If
			Return img
		End Function

		Protected Function LoadImage() As Bitmap
			Dim conn As SqlConnection = DBManager.GetUnmanagedConnection()

			Try
				Dim cmd As SqlCommand = GetLoadSQLCommand()

				cmd.Connection = conn

				cmd.Parameters.Add("@ID", id)

				Dim dr As SqlDataReader = cmd.ExecuteReader()

				Dim found As Boolean = dr.Read()
				Debug.Assert(found)

				Dim buffer As Byte() = New Byte(Constants.PICTURE_MAX_SIZE) {}
				dr.GetBytes(GetImageDataOrdinal(dr), 0, buffer, 0, Constants.PICTURE_MAX_SIZE)

				img = New Bitmap(New MemoryStream(buffer))

				dr.Close()
			Finally
				conn.Close()
			End Try

			Return img
		End Function

		Protected Sub DoInsert()
			Dim conn As SqlConnection = DBManager.GetUnmanagedConnection()
			Dim tran As SqlTransaction = conn.BeginTransaction()

			Try
				' Insert a new picture
				Dim cmd As SqlCommand = GetInsertSQLCommand()

				cmd.Connection = conn
				cmd.Transaction = tran

				' Force inserting the image itself also
				PopulateCommand(cmd, True)

				Dim paramID As SqlParameter = cmd.Parameters.Add("@ID", SqlDbType.Int)
				paramID.Direction = ParameterDirection.Output

				cmd.ExecuteNonQuery()

				id = DirectCast(paramID.Value, Integer)

				tran.Commit()
			Catch e As Exception
				tran.Rollback()
				Throw e
			Finally
				conn.Close()
			End Try
		End Sub

		Protected Sub DoUpdate()
			Dim conn As SqlConnection = DBManager.GetUnmanagedConnection()

			Try
				Dim cmd As SqlCommand = GetUpdateSQLCommand()

				cmd.Connection = conn

				PopulateCommand(cmd)

				cmd.Parameters.Add("@ID", id)

				Dim rows As Integer = cmd.ExecuteNonQuery()
				Debug.Assert(rows = 1)
			Finally
				conn.Close()
			End Try
		End Sub

		' Populates the command with the user's properties
		' NOTE:	skips the ID property, since it's need only on insert
		'			- by default skips the picture if it is null, since it is only loaded on demand
		Protected Sub PopulateCommand(ByVal cmd As SqlCommand)
			PopulateCommand(cmd, False)
		End Sub


		Protected MustOverride Sub LoadFromReader(ByVal dr As SqlDataReader)

		Protected MustOverride Function GetImageDataOrdinal(ByVal dr As SqlDataReader) As Integer

		Protected MustOverride Function GetLoadSQLCommand() As SqlCommand
		Protected MustOverride Function GetInsertSQLCommand() As SqlCommand
		Protected MustOverride Function GetUpdateSQLCommand() As SqlCommand

		Protected MustOverride Sub PopulateCommand(ByVal cmd As SqlCommand, ByVal forcePopulatePicture As Boolean)
	End Class
End Namespace






